﻿Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D

Namespace DirectX

    Module mDirectX

        Public Const FVF_LINEVERT = VertexFormats.Transformed Or VertexFormats.Diffuse

        Public Const FVF_TEXVERT = VertexFormats.Position Or VertexFormats.Texture0

        Public DeviceLost As Boolean
        Public Windowed As Boolean = True

        Public DispMode As DisplayMode
        Public PresentParam As PresentParameters
        Public D3D As Direct3D.Device
        Public GameSprite As Direct3D.Sprite

        Public GameSurface As Direct3D.Surface

        Public ProFont9 As Fonts.MirFont
        Public ProFont14 As Fonts.MirFont

        Public ScreenRect As Rectangle

        Public ColorFormat As Format = Format.A8R8G8B8
        Public ShadowBlend As Single = 0.4F

        Public Enum DrawingMode
            Normal = 0
            Text = 1
            Line = 2
            Tinted = 3
            Overlay = 4
            Shadow = 5
        End Enum

        Public Sub Init()

            DirectX.DispMode.Width = Editor.winWidth
            DirectX.DispMode.Height = Editor.winHeight
            Main.frmEditor.ClientSize = New Size(DirectX.DispMode.Width, DirectX.DispMode.Height)
            DirectX.DispMode.Format = DirectX.ColorFormat

            DirectX.PresentParam = New PresentParameters()

            SetupPresentParams(DirectX.PresentParam)

            DirectX.D3D = New Direct3D.Device(Manager.Adapters.Default.Adapter, Direct3D.DeviceType.Hardware, Main.frmEditor, CreateFlags.HardwareVertexProcessing Or CreateFlags.PureDevice, DirectX.PresentParam)

            LoadRes()
            CalcScreenRect()

        End Sub

        Private Sub SetupPresentParams(ByRef pp As PresentParameters)

            pp.BackBufferCount = 1
            pp.BackBufferFormat = DirectX.ColorFormat
            pp.BackBufferWidth = DirectX.DispMode.Width
            pp.BackBufferHeight = DirectX.DispMode.Height

            pp.SwapEffect = SwapEffect.Discard
            pp.PresentationInterval = PresentInterval.Default

            pp.ForceNoMultiThreadedFlag = False

            pp.PresentFlag = PresentFlag.None

            pp.Windowed = DirectX.Windowed
            pp.MultiSample = MultiSampleType.None
            pp.MultiSampleQuality = 0

            pp.EnableAutoDepthStencil = True
            pp.AutoDepthStencilFormat = DepthFormat.D16

            pp.DeviceWindow = Main.frmEditor


        End Sub

        Public Sub LoadRes()

            D3D.Transform.View = Microsoft.DirectX.Matrix.OrthoOffCenterLH(0, DispMode.Width, DispMode.Height, 0, 0.0, 1.0)

            SetRenderStates()

            GameSprite = New Direct3D.Sprite(D3D)

            GameSurface = DirectX.D3D.GetBackBuffer(0, 0, BackBufferType.Mono)

            ProFont9 = New Fonts.MirFont(D3D, "ProFontWindows", 9)
            ProFont14 = New Fonts.MirFont(D3D, "ProFontWindows", 14)

        End Sub

        Private Sub SetRenderStates()

            D3D.RenderState.Lighting = False
            D3D.RenderState.AlphaBlendEnable = True
            D3D.RenderState.SourceBlend = Blend.SourceAlpha
            D3D.RenderState.DestinationBlend = Blend.InvSourceAlpha
            D3D.RenderState.AlphaTestEnable = True
            D3D.RenderState.ReferenceAlpha = 0
            D3D.RenderState.AlphaFunction = Compare.Greater
            D3D.RenderState.ZBufferEnable = True
            D3D.RenderState.ZBufferWriteEnable = True
            D3D.RenderState.ZBufferFunction = Compare.LessEqual
            D3D.RenderState.Clipping = True

        End Sub

        Public Sub DeviceRecover()

            'when we lose the device, this code will run

            Try
                DirectX.D3D.TestCooperativeLevel()
            Catch e As DeviceLostException
                'do nothing
            Catch e As DeviceNotResetException

                Try

                    SetupPresentParams(DirectX.PresentParam)

                    DirectX.D3D.Reset(DirectX.PresentParam)
                    DirectX.DeviceLost = False

                    LoadRes()

                Catch bug As DeviceLostException
                    DirectX.DeviceLost = True
                End Try

            End Try

        End Sub

        Public Sub SetResoloution(ByRef w As Integer, ByRef h As Integer)

            'DirectX.GameSprite.Dispose()
            DirectX.GameSurface.Dispose()
            DirectX.ProFont9.Dispose()
            DirectX.ProFont14.Dispose()

            DirectX.DispMode.Width = w
            DirectX.DispMode.Height = h
            DirectX.DispMode.Format = Manager.Adapters.Default.CurrentDisplayMode.Format

            If Windowed Then
                Main.frmEditor.ClientSize = New Size(DirectX.DispMode.Width, DirectX.DispMode.Height)
            End If

            DirectX.PresentParam = New PresentParameters()

            SetupPresentParams(DirectX.PresentParam)

            DirectX.D3D.Reset(DirectX.PresentParam)

            LoadRes()
            CalcScreenRect()

        End Sub

        Private Sub CalcScreenRect()

            ScreenRect = New Rectangle(0, 0, DispMode.Width, DispMode.Height)

        End Sub

        Public Function FixedFontHeight(ByRef text As String, ByRef width As Integer, ByRef charwidth As Integer, ByRef charheight As Integer) As Integer

            Dim length As Integer = text.Length
            Dim charsperrow As Integer = Math.DivRem(width, charwidth, Nothing)
            Dim r As Integer
            Dim rows As Integer = Math.DivRem(length, charsperrow, r)
            If r > 0 Then rows += 1

            Return rows * charheight

        End Function

        Public Sub BlitD3D(ByRef tex As Texture, ByRef x As Double, ByRef y As Double, ByVal w As Double, ByVal h As Double, Optional ByRef z As Single = 0.0, Optional ByVal zoom As Double = 1.0F)

            If Not tex Is Nothing Then

                Dim mat As Matrix
                Dim result As Matrix

                result = Matrix.Identity()
                mat = Matrix.Transformation2D(New Vector2(0.0F, 0.0F), 0.0F, New Vector2(1.0F, 1.0F), New Vector2(0.0F, 0.0F), 0.0F, New Vector2(x, y))
                result = Matrix.Multiply(result, mat)
                mat = Matrix.Scaling(New Vector3(zoom, zoom, 1.0F))
                result = Matrix.Multiply(result, mat)


                DirectX.GameSprite.Transform = result

                GameSprite.Draw(tex, New Rectangle(0, 0, w, h), New Vector3(0, 0, 0), New Vector3(0, 0, z), Color.White)

                'Exit Sub

                'DirectX.D3D.SetTransform(Microsoft.DirectX.Direct3D.TransformType.Texture1, result)

                'Static sd As SurfaceDescription
                'sd = tex.GetLevelDescription(0)

                'Static verts(3) As CustomVertex.PositionTextured

                'verts(0).Tu = 0.0F
                'verts(0).Tv = 0.0F

                'verts(1).Tu = 1.0F
                'verts(1).Tv = 0.0F

                'verts(2).Tu = 0.0F
                'verts(2).Tv = 1.0F

                'verts(3).Tu = 1.0F
                'verts(3).Tv = 1.0F

                'verts(0).X = x
                'verts(0).Y = y
                'verts(0).Z = z

                'verts(1).X = x + sd.Width
                'verts(1).Y = y
                'verts(1).Z = z

                'verts(2).X = x
                'verts(2).Y = y + sd.Height
                'verts(2).Z = z

                'verts(3).X = x + sd.Width
                'verts(3).Y = y + sd.Height
                'verts(3).Z = z

                'DirectX.D3D.VertexFormat = DirectX.FVF_TEXVERT
                'DirectX.D3D.SetTexture(0, tex)
                'DirectX.D3D.DrawUserPrimitives(PrimitiveType.TriangleStrip, 2, verts)


            End If

        End Sub

        Public Sub Shutdown()

            DirectX.DispMode = Nothing
            DirectX.PresentParam = Nothing

            DirectX.D3D.Dispose()
            DirectX.D3D = Nothing


        End Sub

    End Module

End Namespace